﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Threading;

namespace RecommendatioNetwork
{
    
    public class Sender
    {
        private Repository repository;

        public  Sender (Repository repository){
            this.repository = repository;
        }

        public void SearchComments(Search search)
        {
            foreach (KeyValuePair<Uri, Ranking> kvp in repository.UrisRank)
            {
                try
                {
                    kvp.Value.Request++;// uriwr.Request++;
                    Channel chan = new Channel(kvp.Key);
                    IContract client = chan.SingleChannel;
                    client.Search(search);
                    chan.Dispose();
                }
                catch (Exception)
                {
                    kvp.Value.RequestFailed++;
                    repository.OnNeighborsChanged(EventArgs.Empty); //************
                    continue;
                }

            }

        }
        
        public void Routing(Search search)
        {
            Channel chan = null;
            IContract client = null;
            foreach (KeyValuePair<Uri, Ranking> kvp in  repository.UrisRank)
            {

                //condizione di controllo che evita di reinstradare la richiesta al richiedente della richiesta stessa
                if (!string.Equals(kvp.Key.OriginalString, search.Uri.OriginalString, StringComparison.InvariantCultureIgnoreCase))
                {
                    try
                    {
                        chan = new Channel(kvp.Key);
                        client = chan.SingleChannel;
                        search.TimeToLive--;
                        client.Search(search);
                        chan.Dispose();
                    }
                    catch (System.ServiceModel.EndpointNotFoundException) { chan.Dispose(); continue; }
                    catch (Exception) { chan.Dispose(); continue; }
                }
            }
        }

        public void SendResponse(Search search,List<Comment> result)
        {
            Channel chan = null;
            IContract client = null;
            foreach (Comment comment in result)
            {

                try
                {
                    chan = new Channel(search.Uri);
                    client = chan.SingleChannel;
                    client.AddResponseSearch(comment, repository.MyUri, search);
                    chan.Dispose();
                }
                catch (System.ServiceModel.EndpointNotFoundException)
                {
                    //logica relativa al lancio dello spooler
                    chan.Dispose();
                    // se è la lista è vuota riattivo il thread
                    if (repository.QueueResponse.Count == 0)
                    {
                        repository.QueueResponse.Enqueue(new Packet() { Comment = comment, Search = search, UriToSend = search.Uri });

                        ThreadStart threadSearchInMyComments = delegate { Spooler(); };
                        new Thread(threadSearchInMyComments).Start();
                        
                    }
                    else repository.QueueResponse.Enqueue(new Packet() { Comment = comment, Search = search, UriToSend = search.Uri });
                    continue;
                }
                catch (Exception) { chan.Dispose(); /*MessageBox.Show("questa eccezzione:" + ee.ToString());*/ }

            }
        }
    
        public void NewRequestAtNewNeighbors(Uri uri)
        {
            foreach (Search search in repository.ActiveSearch.Keys)
            {
                Channel chan = null;
                IContract client = null;
                try
                {
                    chan = new Channel(uri);
                    client = chan.SingleChannel;
                    search.TimeToLive--;
                    client.Search(search);
                    chan.Dispose();
                }
                catch (System.ServiceModel.EndpointNotFoundException) { chan.Dispose(); continue; }
                catch (Exception) { chan.Dispose(); continue; }
            }
        }

        public void Spooler()
        {
            //MessageBox.Show("Try Resend");

            while (repository.QueueResponse.Count != 0)
            {
                Channel chan = null;
                IContract client = null;
                Packet packet = null;
                try
                {

                    System.Threading.Thread.Sleep(repository.Configuration.CadenceSpooler);
                    packet = repository.QueueResponse.Dequeue();
                    if (repository.Configuration.NumberOfResending != 0)
                    {
                        repository.Configuration.NumberOfResending--;
                        chan = new Channel(packet.UriToSend);
                        client = chan.SingleChannel;
                        client.AddResponseSearch(packet.Comment, repository.MyUri, packet.Search);
                        chan.Dispose();
                    }
                }
                catch (System.ServiceModel.EndpointNotFoundException)
                {
                    //MessageBox.Show("catch spooler");
                    chan.Dispose();
                    repository.QueueResponse.Enqueue(packet);
                    continue;
                }
                catch (Exception ee) { MessageBox.Show(ee.ToString()); }
            }

        }

    }
}
